/*******************************************************************/
/* @ All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.        */
/*                                                                 */
/*  NAME      = frreport_session_mng.c                             */
/*  NOTE      = 上报信息缓存管理                                   */
/*  DATE      = 2016/03/02                                         */
/*******************************************************************/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <strings.h>

#include "frcomm.h"
#include "frlog.h"
#include "frmem.h"
#include "frlist.h"
#include "frhash2.h"

#include "frreport_session_mng.h"

#define APM_HASH_DATA_SIZE     100000

FR_STATIC Frhash_header *g_p_st_hash_data = NULL;
FR_STATIC Frhash_header *g_p_st_hash_node_free = NULL;
FR_STATIC pthread_spinlock_t g_splock_report_mng;
FR_STATIC unsigned int g_ui_timeout_report_session=10; //单位sec

/*******************************************************************************
*  FUNC     :  上报信息缓存管理资源初始化
*  ARGS     :
*  RTN      :  FR_SUCC:成功,FR_FAIL:失败
*  NOTE     :
*******************************************************************************/
int frreport_session_mng_init(unsigned int ui_hash_size)
{
    pthread_spin_init(&g_splock_report_mng, 0);

    if(ui_hash_size <= 0)
        ui_hash_size = APM_HASH_DATA_SIZE;

    g_p_st_hash_data = frhash2_create2(ui_hash_size);
    g_p_st_hash_node_free = frhash2_create2(100);
    if(g_p_st_hash_data == NULL || g_p_st_hash_node_free == NULL)
    {
        if(g_p_st_hash_data)
            frhash2_free2(g_p_st_hash_data, NULL);
        if(g_p_st_hash_node_free)
            frhash2_free2(g_p_st_hash_node_free, NULL);
        pthread_spin_destroy(&g_splock_report_mng);
        FRLOG_ERROR_DETAIL("frhash2_create2 err");
        return FR_FAIL;
    }

    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  释放节点内容
*  ARGS     :  p_node
*  RTN      :
*  NOTE     :
*******************************************************************************/
FR_STATIC void __frreport_session_data_free(Frlist_node* p_st_node)
{
    Frlist_node* p_st_node_find=NULL;
    Frreport_session_data *p_session_data=NULL;
    int i_l7_proto = 0;
    pf_report_session_data_free pf_free=NULL;

    if( p_st_node == NULL)
        return;
    //获取l7_proto
    p_session_data = (Frreport_session_data *)FRLIST_GET_NODE_DATA(p_st_node);
    if(p_session_data == NULL)
        return;
    i_l7_proto = p_session_data->i_l7_proto;

    //获取释放函数指针
    p_st_node_find = frhash2_getLong(g_p_st_hash_node_free, i_l7_proto);
    if(p_st_node_find == NULL)
        return;
    pf_free = (pf_report_session_data_free)FRLIST_GET_NODE_DATA(p_st_node_find);
    if(pf_free == NULL)
        return;
    pf_free(&p_session_data->p_data);
    frfree(p_session_data);

    return;
}

/*******************************************************************************
*  FUNC     :  清除超时数据
*  ARGS     :
*  RTN      :
*  NOTE     :
*******************************************************************************/
void frreport_session_mng_clean(void)
{
    int i_loop=0;
    Frlist_header *p_st_lst_hdr = NULL;
    Frlist_node *p_st_node, *p_st_node_del=NULL;
    Frreport_session_data *p_st_report_sessoin=NULL;
    struct timeval st_timeval_now;
    long l_timeout=0;

    gettimeofday (&st_timeval_now, NULL);

    pthread_spin_lock(&g_splock_report_mng);
    if(g_p_st_hash_node_free == NULL || frhash2_getCount(g_p_st_hash_node_free) <= 0)
    {
        pthread_spin_unlock(&g_splock_report_mng);
        return;
    }

    FRHASH_LOOP(i_loop, g_p_st_hash_data, p_st_lst_hdr)
    {
        p_st_node = FRLIST_FIRST_NODE(p_st_lst_hdr);
        while(p_st_node)
        {
            p_st_node_del = NULL;
            if(p_st_node && p_st_node->data)
            {
                p_st_report_sessoin = (Frreport_session_data *)(p_st_node->data);
                l_timeout = frtime_diff(&p_st_report_sessoin->st_timeval_upd, &st_timeval_now);
                if(l_timeout < 0 || l_timeout/1000000 >= g_ui_timeout_report_session)
                    p_st_node_del = p_st_node;
            }
            p_st_node = FRLIST_NEXT_NODE(p_st_node);
            if(p_st_node_del)
                frhash2_del(g_p_st_hash_data, p_st_node_del, __frreport_session_data_free);
        }
    }
    pthread_spin_unlock(&g_splock_report_mng);

    return;
}

/*******************************************************************************
*  FUNC     :  设置上报信息缓存管理的关联信息
*  ARGS     :
*  RTN      :
*  NOTE     :
*******************************************************************************/
void frreport_session_mng_setRef(Frreport_session_ref *p_st_report_session_ref)
{
    if(p_st_report_session_ref == NULL)
        return;

    p_st_report_session_ref->p_hash_hdr_data = g_p_st_hash_data;
    p_st_report_session_ref->p_hash_hdr_node_free = g_p_st_hash_node_free;
    p_st_report_session_ref->p_splock = &g_splock_report_mng;
    return;
}


/*******************************************************************************
*  FUNC     :  上报信息缓存管理资源释放
*  ARGS     :
*  RTN      :
*  NOTE     :  释放时调用协议模块函数,所以必须在协议管理模块释放前调用
*******************************************************************************/
void frreport_session_mng_destory(void)
{
    if(!g_p_st_hash_data)
        return;

    pthread_spin_destroy(&g_splock_report_mng);

    if(g_p_st_hash_data)
        frhash2_free2(g_p_st_hash_data, __frreport_session_data_free);
    if(g_p_st_hash_node_free)
        frhash2_free2(g_p_st_hash_node_free, NULL);

    g_p_st_hash_data = NULL;

    return;
}


